<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>图像单主体检测</title>
    <style>
        body {
            font-family: "Microsoft YaHei", sans-serif;
            padding: 20px;
            background: #f8f9fa;
            color: #333;
        }
        .container {
            max-width: 1000px;
            margin: 0 auto;
            background: white;
            padding: 30px;
            border-radius: 10px;
            box-shadow: 0 2px 15px rgba(0,0,0,0.1);
        }
        h2 {
            color: #2c3e50;
            margin-bottom: 30px;
            text-align: center;
            font-size: 24px;
        }
        .test-container {
            display: flex;
            gap: 30px;
            margin-top: 30px;
        }
        .left-panel {
            flex: 1;
            padding: 20px;
            background: #fff;
            border-radius: 8px;
            border: 1px solid #e1e1e1;
        }
        .right-panel {
            flex: 1;
            padding: 20px;
            background: #fff;
            border-radius: 8px;
            border: 1px solid #e1e1e1;
        }
        .test-form {
            margin-bottom: 20px;
            display: flex;
            gap: 10px;
            align-items: center;
        }
        .file-input-wrapper {
            position: relative;
            overflow: hidden;
            display: inline-block;
        }
        .file-input-wrapper input[type=file] {
            font-size: 100px;
            position: absolute;
            left: 0;
            top: 0;
            opacity: 0;
            cursor: pointer;
        }
        .file-input-trigger {
            background: #f8f9fa;
            border: 1px solid #ddd;
            padding: 8px 16px;
            border-radius: 4px;
            cursor: pointer;
            display: inline-block;
        }
        .test-btn {
            background: #3498db;
            color: white;
            border: none;
            padding: 8px 20px;
            border-radius: 4px;
            cursor: pointer;
            transition: background 0.3s;
        }
        .test-btn:hover {
            background: #2980b9;
        }
        .preview-area {
            margin: 20px 0;
            text-align: center;
            min-height: 200px;
            display: flex;
            align-items: center;
            justify-content: center;
            background: #f8f9fa;
            border-radius: 8px;
            border: 2px dashed #ddd;
            position: relative;
            overflow: hidden;
        }
        .preview-area img {
            max-width: 100%;
            max-height: 300px;
            border-radius: 4px;
            display: none;
        }
        .detection-box {
            position: absolute;
            border: 2px solid #3498db;
            pointer-events: none;
            box-shadow: 0 0 0 1px rgba(255,255,255,0.5);
            transition: all 0.3s;
        }
        .detection-label {
            position: absolute;
            top: -25px;
            left: 0;
            background: #3498db;
            color: white;
            padding: 2px 6px;
            border-radius: 4px;
            font-size: 12px;
            white-space: nowrap;
        }
        .result-area {
            background: #f8f9fa;
            padding: 20px;
            border-radius: 8px;
            min-height: 200px;
            font-family: "Microsoft YaHei", sans-serif;
            font-size: 14px;
            line-height: 1.6;
            overflow: auto;
        }
        .result-list {
            padding: 0;
        }
        .result-item {
            margin-bottom: 20px;
            padding: 15px;
            background: white;
            border-radius: 8px;
            box-shadow: 0 2px 5px rgba(0,0,0,0.1);
        }
        .result-item p {
            margin: 8px 0;
            padding-left: 10px;
            border-left: 3px solid #e8e8e8;
        }
        .result-item .title {
            font-size: 16px;
            color: #2c3e50;
            font-weight: bold;
            margin-bottom: 15px;
            padding-left: 0;
            border-left: none;
        }
        .result-item .location {
            border-left-color: #3498db;
        }
        .result-item .location-detail {
            margin-left: 20px;
            color: #666;
        }
        .error {
            color: #e74c3c;
            padding: 10px;
            background: #fdf3f2;
            border-radius: 4px;
        }
        .panel-title {
            margin-top: 0;
            margin-bottom: 20px;
            color: #2c3e50;
            font-size: 18px;
        }
        .options {
            margin: 10px 0;
        }
        .api-docs {
            margin-top: 40px;
            padding: 20px;
            background: #fff;
            border-radius: 8px;
            border: 1px solid #e1e1e1;
        }
        
        .api-docs details {
            margin-bottom: 20px;
        }
        
        .api-docs summary {
            cursor: pointer;
            color: #2c3e50;
            font-weight: bold;
            margin-bottom: 15px;
        }
        
        .api-docs pre {
            background: #f8f9fa;
            padding: 15px;
            border-radius: 4px;
            overflow-x: auto;
            margin: 10px 0;
        }
        
        .api-docs code {
            font-family: Consolas, Monaco, 'Courier New', monospace;
            font-size: 14px;
        }
        
        .api-docs table {
            width: 100%;
            border-collapse: collapse;
            margin: 10px 0;
        }
        
        .api-docs th, .api-docs td {
            padding: 10px;
            border: 1px solid #ddd;
            text-align: left;
        }
        
        .api-docs th {
            background: #f8f9fa;
            font-weight: bold;
        }
        
        .api-section {
            margin-bottom: 20px;
        }
        
        .api-section h4 {
            color: #2c3e50;
            margin: 15px 0 10px;
        }
    </style>
</head>
<body>
    <div class="container">
        <h2>图像单主体检测</h2>
        <div class="test-container">
            <div class="left-panel">
                <h3 class="panel-title">图片上传</h3>
                <div class="test-form">
                    <div class="file-input-wrapper">
                        <div class="file-input-trigger">选择图片</div>
                        <input type="file" id="testImage" accept="image/*" onchange="previewImage(event)">
                    </div>
                    <button onclick="testAPI()" class="test-btn">开始检测</button>
                </div>
                <div class="options">
                    <label>
                        <input type="checkbox" id="withFace" checked> 包含人脸区域
                    </label>
                </div>
                <div class="preview-area">
                    <img id="preview" alt="预览图">
                </div>
            </div>
            <div class="right-panel">
                <h3 class="panel-title">检测结果</h3>
                <div id="result" class="result-area"></div>
            </div>
        </div>

        <!-- API文档部分 -->
        <div class="api-docs">
            <details>
                <summary>API 文档</summary>
                <div class="api-section">
                    <h4>接口描述</h4>
                    <p>该接口用于检测图片中的主体位置，返回主体区域的坐标信息。</p>
                </div>
                
                <div class="api-section">
                    <h4>请求URL</h4>
                    <pre><code>POST /detection/process</code></pre>
                </div>
                
                <div class="api-section">
                    <h4>请求参数</h4>
                    <table>
                        <tr>
                            <th>参数名</th>
                            <th>必选</th>
                            <th>类型</th>
                            <th>说明</th>
                        </tr>
                        <tr>
                            <td>image</td>
                            <td>是</td>
                            <td>file</td>
                            <td>图片文件，base64编码后大小不超过4M，最短边至少15px，最长边最大4096px，支持jpg/png/bmp格式</td>
                        </tr>
                        <tr>
                            <td>with_face</td>
                            <td>否</td>
                            <td>number</td>
                            <td>如果检测主体是人，主体区域是否带上人脸部分，0-不带人脸区域，其他-带人脸区域。默认为1</td>
                        </tr>
                    </table>
                </div>
                
                <div class="api-section">
                    <h4>返回参数</h4>
                    <table>
                        <tr>
                            <th>参数名</th>
                            <th>类型</th>
                            <th>说明</th>
                        </tr>
                        <tr>
                            <td>success</td>
                            <td>boolean</td>
                            <td>请求是否成功</td>
                        </tr>
                        <tr>
                            <td>result</td>
                            <td>object</td>
                            <td>检测结果</td>
                        </tr>
                        <tr>
                            <td>result.log_id</td>
                            <td>uint64</td>
                            <td>唯一的日志ID</td>
                        </tr>
                        <tr>
                            <td>result.result.left</td>
                            <td>uint32</td>
                            <td>表示主体位置的长方形左上顶点的水平坐标</td>
                        </tr>
                        <tr>
                            <td>result.result.top</td>
                            <td>uint32</td>
                            <td>表示主体位置的长方形左上顶点的垂直坐标</td>
                        </tr>
                        <tr>
                            <td>result.result.width</td>
                            <td>uint32</td>
                            <td>表示主体位置的长方形的宽度，单位px</td>
                        </tr>
                        <tr>
                            <td>result.result.height</td>
                            <td>uint32</td>
                            <td>表示主体位置的长方形的高度，单位px</td>
                        </tr>
                    </table>
                </div>
                
                <div class="api-section">
                    <h4>返回示例</h4>
                    <pre><code>{
    "success": true,
    "result": {
        "log_id": "7357875020059572776",
        "result": {
            "left": 117,
            "top": 76,
            "width": 186,
            "height": 293
        }
    }
}</code></pre>
                </div>
                
                <div class="api-section">
                    <h4>Python调用示例</h4>
                    <pre><code>import requests

# 上传图片文件
files = {'image': open('image.jpg', 'rb')}
data = {'with_face': '1'}  # 可选参数
response = requests.post('http://your-domain/detection/process', files=files, data=data)

# 处理响应
if response.status_code == 200:
    result = response.json()
    if result['success']:
        # 处理检测结果
        detection = result['result']['result']
        print(f"主体位置: 左上角({detection['left']}, {detection['top']}), "
              f"宽度: {detection['width']}, 高度: {detection['height']}")
    else:
        print(result['message'])</code></pre>
                </div>
            </details>
        </div>
    </div>

    <script>
        function previewImage(event) {
            const file = event.target.files[0];
            if (file) {
                const reader = new FileReader();
                reader.onload = function(e) {
                    const preview = document.getElementById('preview');
                    preview.src = e.target.result;
                    preview.style.display = 'block';
                    document.getElementById('result').textContent = '';
                    
                    // 清除之前的检测框
                    const boxes = document.querySelectorAll('.detection-box');
                    boxes.forEach(box => box.remove());
                }
                reader.readAsDataURL(file);
            }
        }

        function formatResult(data) {
            if (!data.success) {
                return `<div class="error">${data.message}</div>`;
            }

            const result = data.result.result;
            let html = '<div class="result-list">';
            
            html += `
                <div class="result-item">
                    <p class="title">检测结果</p>
                    <p class="location">
                        主体位置信息：
                        <div class="location-detail">
                            - 左上角坐标：(${result.left}, ${result.top})<br>
                            - 尺寸：${result.width} x ${result.height} 像素
                        </div>
                    </p>
                </div>
            `;
            
            html += '</div>';
            return html;
        }

        function drawDetectionBox(result) {
            const previewArea = document.querySelector('.preview-area');
            const img = document.getElementById('preview');
            
            // 清除之前的检测框
            const boxes = document.querySelectorAll('.detection-box');
            boxes.forEach(box => box.remove());
            
            // 获取图片在预览区域中的实际尺寸和位置
            const imgRect = img.getBoundingClientRect();
            
            // 计算缩放比例
            const scaleX = img.naturalWidth / imgRect.width;
            const scaleY = img.naturalHeight / imgRect.height;
            
            // 创建检测框
            const box = document.createElement('div');
            box.className = 'detection-box';
            
            // 计算检测框的位置和大小
            const left = (result.left / scaleX) + imgRect.left - previewArea.offsetLeft;
            const top = (result.top / scaleY) + imgRect.top - previewArea.offsetTop;
            const width = result.width / scaleX;
            const height = result.height / scaleY;
            
            box.style.left = `${left}px`;
            box.style.top = `${top}px`;
            box.style.width = `${width}px`;
            box.style.height = `${height}px`;
            
            // 添加标签显示尺寸
            const label = document.createElement('div');
            label.className = 'detection-label';
            label.textContent = `${Math.round(width * scaleX)}×${Math.round(height * scaleY)}`;
            box.appendChild(label);
            
            previewArea.appendChild(box);
        }

        async function testAPI() {
            const fileInput = document.getElementById('testImage');
            const file = fileInput.files[0];
            if (!file) {
                alert('请先选择图片');
                return;
            }

            const formData = new FormData();
            formData.append('image', file);
            formData.append('with_face', document.getElementById('withFace').checked ? '1' : '0');

            try {
                document.getElementById('result').textContent = '检测中...';
                const response = await fetch('/detection/process', {
                    method: 'POST',
                    body: formData
                });

                const data = await response.json();
                document.getElementById('result').innerHTML = formatResult(data);
                
                // 如果检测成功，绘制检测框
                if (data.success && data.result && data.result.result) {
                    drawDetectionBox(data.result.result);
                }
                
            } catch (error) {
                document.getElementById('result').textContent = `请求错误：${error.message}`;
            }
        }
    </script>
</body>
</html> 